import os
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from collections import defaultdict, Counter
import datetime
import re

# 设置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
# 分析data/数据强势情况
class StockAnalyzer:
    def __init__(self, data_dir, start_date=None, end_date=None):
        self.data_dir = data_dir
        self.stock_data = {}
        self.stock_frequency = Counter()
        self.stock_info = {}
        self.start_date = start_date  # 分析开始日期
        self.end_date = end_date    # 分析结束日期
        self.load_data()
        
    def load_data(self):
        """加载所有股票数据文件，可根据日期范围筛选"""
        print(f"正在从 {self.data_dir} 加载数据...")
        files = [f for f in os.listdir(self.data_dir) if f.endswith('.txt')]
        files.sort()  # 按日期排序
        
        # 根据日期范围筛选文件
        if self.start_date or self.end_date:
            filtered_files = []
            for file in files:
                date_str = file.split('.')[0]
                if self.start_date and date_str < self.start_date:
                    continue
                if self.end_date and date_str > self.end_date:
                    continue
                filtered_files.append(file)
            files = filtered_files
            print(f"根据日期范围筛选后，共有 {len(files)} 个交易日的数据")
        
        for file in files:
            date_str = file.split('.')[0]
            file_path = os.path.join(self.data_dir, file)
            try:
                # 读取文件数据
                df = pd.read_csv(file_path, sep='\t')
                # 记录每只股票出现的次数
                for _, row in df.iterrows():
                    stock_code = row['代码']
                    self.stock_frequency[stock_code] += 1
                    
                    # 保存股票信息
                    if stock_code not in self.stock_info:
                        self.stock_info[stock_code] = {
                            '名称': row['名称'],
                            '行业': '未知',  # 数据中没有行业信息，可以后续添加
                            '最早出现日期': date_str,
                            '最新出现日期': date_str,
                            '出现次数': 1,
                            '平均涨跌幅': row['涨跌幅'],
                            '累计涨跌幅': row['涨跌幅'],
                            '最大涨幅': row['涨跌幅'],
                            '最小涨幅': row['涨跌幅'],
                            '平均换手率': row['换手率'] if '换手率' in row else 0,
                            '平均成交量': row['成交量'],
                            '市盈率': row['市盈率-动态'] if '市盈率-动态' in row else 0,
                            '市净率': row['市净率'] if '市净率' in row else 0,
                            '60日涨跌幅': row['60日涨跌幅'] if '60日涨跌幅' in row else 0,
                            '年初至今涨跌幅': row['年初至今涨跌幅'] if '年初至今涨跌幅' in row else 0,
                            '数据': [{
                                '日期': date_str,
                                '价格': row['最新价'],
                                '涨跌幅': row['涨跌幅'],
                                '成交量': row['成交量'],
                                '换手率': row['换手率'] if '换手率' in row else 0
                            }]
                        }
                    else:
                        # 更新股票信息
                        info = self.stock_info[stock_code]
                        info['最新出现日期'] = date_str
                        info['出现次数'] += 1
                        info['累计涨跌幅'] += row['涨跌幅']
                        info['平均涨跌幅'] = info['累计涨跌幅'] / info['出现次数']
                        info['最大涨幅'] = float(max(float(info['最大涨幅']), float(row['涨跌幅'])))
                        info['最小涨幅'] = float(min(float(info['最小涨幅']), float(row['涨跌幅'])))
                        info['平均换手率'] = (info['平均换手率'] * (info['出现次数'] - 1) + 
                                         (row['换手率'] if '换手率' in row else 0)) / info['出现次数']
                        info['平均成交量'] = (info['平均成交量'] * (info['出现次数'] - 1) + row['成交量']) / info['出现次数']
                        info['市盈率'] = row['市盈率-动态'] if '市盈率-动态' in row else info['市盈率']
                        info['市净率'] = row['市净率'] if '市净率' in row else info['市净率']
                        info['60日涨跌幅'] = row['60日涨跌幅'] if '60日涨跌幅' in row else info['60日涨跌幅']
                        info['年初至今涨跌幅'] = row['年初至今涨跌幅'] if '年初至今涨跌幅' in row else info['年初至今涨跌幅']
                        info['数据'].append({
                            '日期': date_str,
                            '价格': row['最新价'],
                            '涨跌幅': row['涨跌幅'],
                            '成交量': row['成交量'],
                            '换手率': row['换手率'] if '换手率' in row else 0
                        })
                
                # 保存每日数据
                self.stock_data[date_str] = df
                
            except Exception as e:
                print(f"处理文件 {file} 时出错: {e}")
        
        print(f"共加载 {len(files)} 个交易日的数据，包含 {len(self.stock_info)} 只股票")
    
    def get_frequent_stocks(self, min_frequency=1):
        """获取出现频率较高的股票"""
        return [code for code, freq in self.stock_frequency.items() if freq >= min_frequency]
    
    def calculate_stability_score(self, stock_code):
        """计算股票稳定性得分"""
        if stock_code not in self.stock_info:
            return 0
        
        info = self.stock_info[stock_code]
        if info['出现次数'] < 2:  # 降低要求，只要出现2次以上即可
            return 0
        
        # 计算涨跌幅的标准差
        price_changes = [data['涨跌幅'] for data in info['数据']]
        std_dev = np.std(price_changes)
        
        # 稳定性得分 = 平均涨跌幅 / (标准差 + 1)，加1是为了避免除以0
        stability = info['平均涨跌幅'] / (std_dev + 1)
        
        return stability
    
    def calculate_momentum_score(self, stock_code):
        """计算股票动量得分"""
        if stock_code not in self.stock_info:
            return 0
        
        info = self.stock_info[stock_code]
        if info['出现次数'] < 2:  # 降低要求，只要出现2次以上即可
            return 0
        
        # 最近的涨跌幅权重更高
        recent_changes = [data['涨跌幅'] for data in info['数据'][-3:]]
        if not recent_changes:
            return 0
        
        # 动量得分 = 最近涨跌幅的加权平均
        weights = np.array([0.5, 0.3, 0.2])[:len(recent_changes)]
        weights = weights / weights.sum()  # 归一化权重
        momentum = np.average(recent_changes, weights=weights)
        
        return momentum
    
    def calculate_volume_score(self, stock_code):
        """计算成交量得分"""
        if stock_code not in self.stock_info:
            return 0
        
        info = self.stock_info[stock_code]
        if info['出现次数'] < 2:  # 降低要求，只要出现2次以上即可
            return 0
        
        # 计算最近成交量变化
        volumes = [data['成交量'] for data in info['数据']]
        if len(volumes) < 2:
            return 0
        
        # 成交量增长率
        volume_growth = (volumes[-1] / volumes[0] - 1) if volumes[0] > 0 else 0
        
        # 成交量得分 = 成交量增长率 * 平均换手率
        volume_score = volume_growth * info['平均换手率'] / 10  # 除以10进行归一化
        
        return volume_score
    
    def calculate_comprehensive_score(self, stock_code):
        """计算综合得分"""
        if stock_code not in self.stock_info:
            return 0
        
        info = self.stock_info[stock_code]
        
        # 各项指标得分
        stability = self.calculate_stability_score(stock_code)
        momentum = self.calculate_momentum_score(stock_code)
        volume = self.calculate_volume_score(stock_code)
        frequency = info['出现次数'] / 10  # 归一化频率得分
        
        # 综合得分 = 稳定性*0.3 + 动量*0.4 + 成交量*0.2 + 频率*0.1
        score = stability * 0.3 + momentum * 0.4 + volume * 0.2 + frequency * 0.1
        
        return score
    
    def get_top_stocks(self, n=10, min_frequency=1):
        """获取综合评分最高的前N只股票"""
        frequent_stocks = self.get_frequent_stocks(min_frequency)
        
        # 计算每只股票的综合得分
        stock_scores = [(code, self.calculate_comprehensive_score(code)) for code in frequent_stocks]
        
        # 按得分降序排序
        stock_scores.sort(key=lambda x: x[1], reverse=True)
        
        return stock_scores[:n]
    
    def get_stock_recommendation_reasons(self, stock_code):
        """获取股票推荐理由"""
        if stock_code not in self.stock_info:
            return "无法找到该股票的信息"
        
        info = self.stock_info[stock_code]
        reasons = []
        
        # 基于出现频率的理由
        if info['出现次数'] >= 2:  # 降低要求，只要出现2次以上即可
            reasons.append(f"该股票在分析期间多次出现({info['出现次数']}次)，表明具有持续的市场关注度")
        
        # 基于平均涨跌幅的理由
        if info['平均涨跌幅'] > 1:  # 降低要求，只要平均涨幅大于1%即可
            reasons.append(f"平均涨幅较高({info['平均涨跌幅']:.2f}%)，表现优于大多数股票")
        
        # 基于稳定性的理由
        stability = self.calculate_stability_score(stock_code)
        if stability > 0.2:  # 降低要求
            reasons.append("涨跌幅波动较小，股价表现稳定")
        
        # 基于动量的理由
        momentum = self.calculate_momentum_score(stock_code)
        if momentum > 1:  # 降低要求
            reasons.append("近期涨势良好，具有较强的上涨动能")
        
        # 基于成交量的理由
        if info['平均换手率'] > 2:  # 降低要求
            reasons.append(f"平均换手率较高({info['平均换手率']:.2f}%)，交易活跃度高")
        
        # 基于长期表现的理由
        if info['60日涨跌幅'] > 5:  # 降低要求
            reasons.append(f"60日涨幅达{info['60日涨跌幅']:.2f}%，中期表现优异")
        
        if info['年初至今涨跌幅'] > 10:  # 降低要求
            reasons.append(f"年初至今涨幅达{info['年初至今涨跌幅']:.2f}%，长期表现优异")
        
        # 如果没有找到特别的理由，给出一个通用理由
        if not reasons:
            reasons.append("综合各项指标表现良好，值得关注")
        
        return "\n".join([f"- {reason}" for reason in reasons])
    
    def generate_recommendation_report(self, n=10, min_frequency=1):
        """生成股票推荐报告"""
        top_stocks = self.get_top_stocks(n, min_frequency)
        
        report = ["# 股票推荐报告\n"]
        start_date = self.start_date if self.start_date else list(self.stock_data.keys())[0]
        end_date = self.end_date if self.end_date else list(self.stock_data.keys())[-1]
        report.append(f"## 分析周期: {start_date} 至 {end_date}\n")
        report.append(f"## 推荐股票列表 (共{len(top_stocks)}只)\n")
        
        for i, (code, score) in enumerate(top_stocks, 1):
            info = self.stock_info[code]
            report.append(f"### {i}. {info['名称']}({code})\n")
            report.append(f"**综合评分**: {score:.2f}\n")
            report.append(f"**最新价格**: {info['数据'][-1]['价格']}元\n")
            report.append(f"**平均涨跌幅**: {info['平均涨跌幅']:.2f}%\n")
            report.append(f"**60日涨跌幅**: {info['60日涨跌幅']:.2f}%\n")
            report.append(f"**年初至今涨跌幅**: {info['年初至今涨跌幅']:.2f}%\n")
            report.append(f"**市盈率**: {info['市盈率']}\n")
            report.append(f"**市净率**: {info['市净率']}\n")
            report.append(f"**平均换手率**: {info['平均换手率']:.2f}%\n")
            report.append("**推荐理由**:\n")
            report.append(self.get_stock_recommendation_reasons(code) + "\n")
            report.append("---\n")
        
        report.append("## 分析方法说明\n")
        report.append("本报告基于以下指标对股票进行综合评分:\n")
        report.append("1. **稳定性**: 评估股票价格波动的稳定程度\n")
        report.append("2. **动量**: 评估股票近期的上涨趋势和力度\n")
        report.append("3. **交易活跃度**: 评估股票的成交量和换手率\n")
        report.append("4. **出现频率**: 评估股票在分析期间的出现次数\n")
        report.append("\n综合得分计算公式: 稳定性*0.3 + 动量*0.4 + 交易活跃度*0.2 + 频率*0.1\n")
        
        return ''.join(report)
    
    def analyze_by_criteria(self, criteria='comprehensive', n=10, min_frequency=1):
        """根据不同标准分析股票"""
        frequent_stocks = self.get_frequent_stocks(min_frequency)
        
        if criteria == 'comprehensive':
            # 综合评分
            scores = [(code, self.calculate_comprehensive_score(code)) for code in frequent_stocks]
            title = "综合评分最高的股票"
            ylabel = "综合评分"
        elif criteria == 'stability':
            # 稳定性评分
            scores = [(code, self.calculate_stability_score(code)) for code in frequent_stocks]
            title = "稳定性最高的股票"
            ylabel = "稳定性评分"
        elif criteria == 'momentum':
            # 动量评分
            scores = [(code, self.calculate_momentum_score(code)) for code in frequent_stocks]
            title = "动量最强的股票"
            ylabel = "动量评分"
        elif criteria == 'volume':
            # 成交量评分
            scores = [(code, self.calculate_volume_score(code)) for code in frequent_stocks]
            title = "交易活跃度最高的股票"
            ylabel = "交易活跃度评分"
        elif criteria == 'frequency':
            # 出现频率
            scores = [(code, self.stock_info[code]['出现次数']) for code in frequent_stocks]
            title = "出现频率最高的股票"
            ylabel = "出现次数"
        elif criteria == 'avg_change':
            # 平均涨跌幅
            scores = [(code, self.stock_info[code]['平均涨跌幅']) for code in frequent_stocks]
            title = "平均涨幅最高的股票"
            ylabel = "平均涨跌幅 (%)"
        elif criteria == 'ytd_change':
            # 年初至今涨跌幅
            scores = [(code, self.stock_info[code]['年初至今涨跌幅']) for code in frequent_stocks]
            title = "年初至今涨幅最高的股票"
            ylabel = "年初至今涨跌幅 (%)"
        else:
            print(f"未知的分析标准: {criteria}")
            return
        
        # 按评分降序排序
        scores.sort(key=lambda x: x[1], reverse=True)
        top_scores = scores[:n]
        
        # 打印详细信息
        print(f"\n{title}:")
        for i, (code, score) in enumerate(top_scores, 1):
            info = self.stock_info[code]
            print(f"{i}. {info['名称']}({code}) - 评分: {score:.2f}, 平均涨跌幅: {info['平均涨跌幅']:.2f}%, "  
                  f"60日涨跌幅: {info['60日涨跌幅']:.2f}%, 年初至今涨跌幅: {info['年初至今涨跌幅']:.2f}%")
        
        return top_scores

def main():
    # 设置数据目录
    data_dir = "data"
    
    # 可以指定日期范围，格式为YYYY-MM-DD，例如：
    # start_date = "2025-08-01"
    # end_date = "2025-09-01"
    # 不指定则分析所有数据
    start_date = "2025-10-09"
    end_date = None
    
    # 创建分析器实例
    analyzer = StockAnalyzer(data_dir, start_date, end_date)
    
    # 自动生成推荐报告
    print("\n生成推荐股票报告...")
    report = analyzer.generate_recommendation_report(10, 2)  # 降低筛选标准，只要出现1次以上即可
    
    # 获取当前月份并创建对应文件夹
    current_month = datetime.datetime.now().strftime('%m月')
    month_dir = os.path.join("analyzer", current_month)
    os.makedirs(month_dir, exist_ok=True)
    
    # 生成带日期的文件名
    date_str = datetime.datetime.now().strftime('%m%d')
    report_path = os.path.join(month_dir, f"{date_str}-recommendation.md")
    
    with open(report_path, 'w', encoding='utf-8') as f:
        f.write(report)
    print(f"推荐报告已生成: {report_path}")
    
    # 打印各种分析结果
    print("\n按不同标准分析股票:")
    print("\n1. 综合评分分析:")
    analyzer.analyze_by_criteria('comprehensive', 10, 1)  # 降低筛选标准
    
    print("\n2. 稳定性分析:")
    analyzer.analyze_by_criteria('stability', 10, 1)  # 降低筛选标准
    
    print("\n3. 动量分析:")
    analyzer.analyze_by_criteria('momentum', 10, 1)  # 降低筛选标准
    
    print("\n4. 交易活跃度分析:")
    analyzer.analyze_by_criteria('volume', 10, 1)  # 降低筛选标准
    
    print("\n5. 出现频率分析:")
    analyzer.analyze_by_criteria('frequency', 10, 1)  # 降低筛选标准
    
    print("\n6. 平均涨跌幅分析:")
    analyzer.analyze_by_criteria('avg_change', 10, 1)  # 降低筛选标准
    
    print("\n7. 年初至今涨跌幅分析:")
    analyzer.analyze_by_criteria('ytd_change', 10, 1)  # 降低筛选标准

if __name__ == "__main__":
    main()